import geopandas as gpd
import pandas as pd
from bpy.types import Operator
import bmesh
import bpy
import math
import numpy
import sys
from mathutils import Vector, Matrix, noise, Quaternion
# sys.path.extend(['', 'D:\\blender-2.92.0-windows64\\2.92\\python\\bin\\python37.zip', 'D:\\blender-2.92.0-windows64\\2.92\\python\\DLLs', 'D:\\blender-2.92.0-windows64\\2.92\\python\\lib', 'D:\\blender-2.92.0-windows64\\2.92\\python\\bin',
#                 'C:\\Users\\tomye\\AppData\\Roaming\\Python\\Python37\\site-packages', 'D:\\blender-2.92.0-windows64\\2.92\\python', 'D:\\blender-2.92.0-windows64\\2.92\\python\\lib\\site-packages'])


def bezier_tangent(pt0=Vector(), pt1=Vector(), pt2=Vector(), pt3=Vector(), step=0.5):
    # Return early if step is out of bounds [0, 1].
    if step <= 0.0:
        return pt1 - pt0
    if step >= 1.0:
        return pt3 - pt2

    # Find coefficients.
    u = 1.0 - step
    ut6 = u * step * 6.0
    tsq3 = step * step * 3.0
    usq3 = u * u * 3.0

    # Find tangent and return.
    return (pt1 - pt0) * usq3 + (pt2 - pt1) * ut6 + (pt3 - pt2) * tsq3


def makeSpline(cu, typ, points):
    spline = cu.splines.new(typ)
    npoints = len(points)
    spline.points.add(npoints-1)    # One point already exists?
    for (n, pt) in enumerate(points):
        spline.points[n].co = pt

    return


def curve_to_mesh(context, curve):
    deg = context.evaluated_depsgraph_get()
    me = bpy.data.meshes.new_from_object(
        curve.evaluated_get(deg), depsgraph=deg)

    # 创建mesh实体
    # new_obj = bpy.data.objects.new(curve.name + "_mesh", me)
    # context.collection.objects.link(new_obj)
    # for o in context.selected_objects:
    #     o.select_set(False)
    # new_obj.matrix_world = curve.matrix_world

    return me


def draw_smooth_pipe(pipeName, pipeData, diameter):
    cu = bpy.data.curves.new(name="MyCurve", type="CURVE")
    ob = bpy.data.objects.new(pipeName, cu)
    bpy.context.scene.collection.objects.link(ob)
    ob.data.bevel_depth = diameter
    #ob.data.use_fill_caps = False

    cu.dimensions = "3D"
    makeSpline(cu, "NURBS", pipeData)
    me = curve_to_mesh(bpy.context, ob)

    # 删除曲线实体
    ob.select_set(True)
    bpy.ops.object.delete(use_global=False)

    return me


def bisect(name, vectors, me, i, plane_no_0, plane_no_1):
    bm = bmesh.new()
    bm.from_mesh(me)

    plane_co = vectors[1]
    if plane_no_0 is None:
        plane_no_0 = bezier_tangent(
            vectors[0], vectors[1], vectors[2], vectors[3], step=0.0).normalized()

    geom = list(bm.verts) + \
        list(bm.edges) + \
        list(bm.faces)

    bmesh.ops.bisect_plane(
        bm,
        geom=geom,
        plane_co=plane_co,
        plane_no=plane_no_0,
        clear_inner=True,
        clear_outer=False)

    geom = list(bm.verts) + \
        list(bm.edges) + \
        list(bm.faces)
    plane_co = vectors[2]
    if plane_no_1 is None:
        plane_no_1 = bezier_tangent(
            vectors[0], vectors[1], vectors[2], vectors[3], step=1.0).normalized()

    bmesh.ops.bisect_plane(
        bm,
        geom=geom,
        plane_co=plane_co,
        plane_no=plane_no_1,
        clear_inner=False,
        clear_outer=True)

    mesh_data = bpy.data.meshes.new(name)
    bm.to_mesh(mesh_data)
    mesh_obj = bpy.data.objects.new(mesh_data.name, mesh_data)
    bpy.context.collection.objects.link(mesh_obj)
    bm.free()
    return plane_no_0, plane_no_1


class Draw_Pipe_Op(Operator):
    bl_idname = "object.draw_pipe"
    bl_label = "draw pipe"
    bl_description = "draw a pipe"

    def execute(self, context):
        # data = gpd.read_file(r"C:\Users\tomye\Documents\中线.geojson").loc[[
        #     0, 1,2,3]]
        data = gpd.read_file(r"C:\Users\tomye\Documents\中线.geojson")
        offsetX = data.geometry[0].centroid.x
        offsetY = data.geometry[0].centroid.y
        offsetZ = 0.0
        print(data.geometry.centroid)
        names = []
        datas = []
        vectors = []
        diameter = 0.0
        for index, row in data.iterrows():
            name = row['管道编码']
            x1 = row.geometry.coords.xy[0][0]
            y1 = row.geometry.coords.xy[1][0]
            z1 = row['起点高程']
            x2 = row.geometry.coords.xy[0][1]
            y2 = row.geometry.coords.xy[1][1]
            z2 = row['终点高程']
            diameter = row['管径']/1000
            if name in names:
                print(name + "已经存在")
            else:
                names.append(name)
                vectors.append(Vector((x1-offsetX, y1-offsetY, z1-offsetZ)))
                datas.append((x1-offsetX, y1-offsetY, z1-offsetZ, 1))
                print(name)

        # 添加第一个点延伸和最后一个点延伸
        data0_x = datas[1][0]+(datas[0][0]-datas[1][0])*2
        data0_y = datas[1][1]+(datas[0][1]-datas[1][1])*2
        data0_z = datas[1][2]+(datas[0][2]-datas[1][2])*2

        count = len(datas)
        data_last_x = datas[count-2][0] + \
            (datas[count-1][0]-datas[count-2][0])*2
        data_last_y = datas[count-2][1] + \
            (datas[count-1][1]-datas[count-2][1])*2
        data_last_z = datas[count-2][2] + \
            (datas[count-1][2]-datas[count-2][2])*2

        vectors.insert(0, Vector((data0_x, data0_y, data0_z)))
        names.insert(0, '0')
        datas.insert(0, (data0_x, data0_y, data0_z, 1))

        vectors.append(Vector((data_last_x, data_last_y, data_last_z)))
        names.append('last')
        datas.append((data_last_x, data_last_y, data_last_z, 1))

        plane_no_0 = None

        for j in range(1, len(names)-2):
            points = datas[j-1:j+3]
            
            # 添加第一个点延伸和最后一个点延伸
            points0_0 = points[1][0]+(points[0][0]-points[1][0])* 1.2
            points0_1 = points[1][1]+(points[0][1]-points[1][1])* 1.2
            points0_2 = points[1][2]+(points[0][2]-points[1][2])* 1.2

            points3_0 = points[2][0]+(points[3][0]-points[2][0])* 1.2
            points3_1 = points[2][1]+(points[3][1]-points[2][1])* 1.2
            points3_2 = points[2][2]+(points[3][2]-points[2][2])* 1.2

            # del(points[0])
            # del(points[2]) # 删除最后一个元素
            points.insert(0,(points0_0,points0_1,points0_2,1))
            points.append((points3_0,points3_1,points3_2,1))
            
            me = draw_smooth_pipe(
                'mesh', points, diameter)  # 返回管线的mesh
            tmp_none, plane_no_0 = bisect(
                names[j], vectors[j-1:j+3], me, j, plane_no_0, None)

        print(offsetX)
        print(offsetY)
        # draw_pipe('pipe1',2.0,2.0,2.0,15.0,1.0,19.0,0.2)

        return {'FINISHED'}
